home *** CD-ROM | disk | FTP | other *** search
/ Nebula 1 / Nebula One.iso / Graphics / Multimedia / Movie3.0 / Source / xanim / xanim_utils.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-06-02  |  31.1 KB  |  1,113 lines

  1.  
  2. /*
  3.  * xanim_utils.c
  4.  *
  5.  * Copyright (C) 1991,1992,1993,1994 by Mark Podlipec. 
  6.  * All rights reserved.
  7.  *
  8.  * This software may be freely copied, modified and redistributed without
  9.  * fee for non-commerical purposes provided that this copyright notice is
  10.  * preserved intact on all copies and modified copies.
  11.  * 
  12.  * There is no warranty or other guarantee of fitness of this software.
  13.  * It is provided solely "as is". The author(s) disclaim(s) all
  14.  * responsibility and liability with respect to this software's usage
  15.  * or its effect upon hardware or computer systems.
  16.  *
  17.  */
  18. #include "xanim.h"
  19.  
  20. void UTIL_Sub_Image();
  21. void UTIL_Create_Clip();
  22. void UTIL_Mapped_To_Mapped();
  23. void UTIL_Mapped_To_Bitmap();
  24. ULONG UTIL_Get_Buffer_Scale();
  25. void UTIL_Scale_Buffer_Pos();
  26. void UTIL_Scale_Pos_Size();
  27. UBYTE *UTIL_Alloc_Scaled();
  28. UBYTE *UTIL_Scale_Mapped();
  29. UBYTE *UTIL_Scale_Bitmap();
  30. void UTIL_Pack_Image();
  31.  
  32. ULONG UTIL_Get_LSB_Long();
  33. ULONG UTIL_Get_LSB_Short();
  34. ULONG UTIL_Get_MSB_Long();
  35. ULONG UTIL_Get_MSB_UShort();
  36. LONG UTIL_Get_MSB_Short();
  37. void UTIL_Mapped_To_Floyd();
  38. LONG CMAP_Find_Closest();
  39. void CMAP_Cache_Init();
  40. void CMAP_Cache_Clear();
  41.  
  42. extern ULONG *xa_scale_row_buff;
  43. extern ULONG xa_scale_row_size;
  44. extern char *xa_scale_buff;
  45. extern ULONG xa_scale_buff_size;
  46. extern LONG xa_dither_flag;
  47. extern ULONG xa_buff_x,xa_buff_y;
  48. extern float xa_bscalex,xa_bscaley;
  49.  
  50.  
  51. void
  52. UTIL_Sub_Image(out,in,xosize,yosize,xipos,yipos,xisize,pix_size)
  53. UBYTE *out,*in;
  54. ULONG xosize,yosize,xipos,yipos,xisize,pix_size;
  55. {
  56.   ULONG y,x;
  57.   UBYTE *in_ptr;
  58.   xosize *= pix_size;
  59.   xisize *= pix_size;
  60.   xipos  *= pix_size;
  61.   for(y=yipos; y < (yipos + yosize); y++)
  62.   {
  63.     in_ptr = (UBYTE *)(in + (y * xisize + xipos));
  64.     x = xosize;
  65.     while(x--) *out++ = *in_ptr++;
  66.   } 
  67. }
  68.  
  69. void
  70. UTIL_Mapped_To_Mapped(out,in,chdr,xipos,yipos,xosize,yosize,xisize,yisize)
  71. UBYTE *out;        /* output image - maybe the same as input image */
  72. UBYTE *in;        /* input image */
  73. XA_CHDR *chdr;        /* color header to remap to */
  74. ULONG xipos,yipos;    /* pos of section in input buffer */
  75. ULONG xosize,yosize;    /* size of section in input buffer */
  76. ULONG xisize,yisize;    /* size of input buffer */
  77. {
  78.   ULONG *map,moff;
  79.   ULONG y,x;
  80.   UBYTE *in_ptr;
  81.  
  82.   map = chdr->map;
  83.   moff = chdr->moff;
  84.   switch(x11_bytes_pixel)
  85.   {
  86.    case 4: /* start from backside to allow for when out = in */
  87.     {
  88.       ULONG *ulp;
  89.       for(y=yosize; y > 0; y--)
  90.       {
  91.         in_ptr = (UBYTE *)(in + (y + yipos - 1) * xisize 
  92.                         + xipos + xosize - 1 );
  93.         ulp =    (ULONG *)(out + ((4 * y * xosize) - 4));
  94.         x = xosize;
  95.         if (moff) while(x--) *ulp-- = map[(*in_ptr--)-moff];
  96.         else while(x--) *ulp-- = map[*in_ptr--];
  97.       }
  98.     }
  99.     break;
  100.    case 2: /* start from backside to allow for when out = in */
  101.     {
  102.       USHORT *usp;
  103.       for(y=yosize; y > 0; y--)
  104.       {
  105.         in_ptr = (UBYTE *)(in + (y + yipos - 1) * xisize 
  106.                         + xipos + xosize - 1 );
  107.         usp =    (USHORT *)(out + ((2 * y * xosize) - 2));
  108.         x = xosize;
  109.         if (moff) while(x--) *usp-- = (USHORT)map[(*in_ptr--)-moff];
  110.         else while(x--) *usp-- = (USHORT)map[*in_ptr--];
  111.       }
  112.     }
  113.     break;
  114.    case 1:
  115.     {
  116.       for(y=yipos; y < (yipos + yosize); y++)
  117.       {
  118.         in_ptr = (UBYTE *)(in + y * xisize + xipos);
  119.         x = xosize;
  120.         if (moff) while(x--) *out++ = (UBYTE)(map[(*in_ptr++)-moff]);
  121.         else while(x--) *out++ = (UBYTE)(map[*in_ptr++]);
  122.       }
  123.     }
  124.     break;
  125.   } /* end switch */ 
  126. }
  127.  
  128. void
  129. UTIL_Create_Clip(out,in,pix_mask,xsize,ysize,pix_size,xosize,bit_order)
  130. UBYTE *out,*in;
  131. ULONG pix_mask,xsize,ysize,pix_size,xosize,bit_order;
  132. {
  133.   register ULONG data_in,bit_mask,x,y,mask_start,mask_end;
  134.   register UBYTE data_out;
  135.  
  136.   if (bit_order == X11_MSB) { mask_start = 0x80; mask_end = 0x01; }
  137.   else { mask_start = 0x01; mask_end = 0x80; }
  138.  
  139.   for(y=0; y<ysize; y++)
  140.   {
  141.     bit_mask = mask_start;
  142.     data_out = 0;
  143.     for(x=0; x < xosize; x++)
  144.     {
  145.       if (x < xsize)
  146.       {
  147.         if (pix_size == 4) 
  148.       { ULONG *ulp = (ULONG *)in;    data_in = *ulp; }
  149.         else if (pix_size == 2)
  150.       { USHORT *usp = (USHORT *)in;    data_in = (ULONG)(*usp); }
  151.         else                data_in = (ULONG)(*in);
  152.         in += pix_size;
  153.         if (data_in != pix_mask) data_out |= bit_mask;
  154.       }
  155.  
  156.       if (bit_mask == mask_end)
  157.       {
  158.         *out++ = data_out;
  159.         bit_mask = mask_start;
  160.     data_out = 0;
  161.       }
  162.       else if (mask_start == 0x01) bit_mask <<= 1;
  163.            else bit_mask >>= 1;
  164.     } /* end of for x */
  165.     if (bit_mask != mask_start) *out++ = data_out;
  166.   } /* end of for y */
  167. }
  168.  
  169. void
  170. UTIL_Mapped_To_Bitmap(out,in,chdr,xpos,ypos,xsize,ysize,width,height,line_size)
  171. UBYTE *out;        /* output buffer */
  172. UBYTE *in;        /* input buffer */
  173. XA_CHDR *chdr;        /* Color Hdr to use */
  174. ULONG xpos,ypos;    /* pos of section in input buffer */
  175. ULONG xsize, ysize;    /* size of section in input buffer */
  176. ULONG width, height;    /* size of buffer */
  177. ULONG line_size;    /* size if bytes of input buffer */
  178. {
  179.   ULONG y,flag,csize;
  180.   ColorReg *cmap;
  181.   register ULONG mask,invert,x,mask_start,mask_end;
  182.   SHORT *imap,*c_ptr,*n_ptr,*err_buff,err,threshold;
  183.   UBYTE data,*o_ptr;
  184.   
  185.   csize = chdr->csize;
  186.   cmap = chdr->cmap;
  187.  
  188.   err_buff = (SHORT *)malloc(xsize * 2 * sizeof(SHORT));
  189.   imap     = (SHORT *)malloc(csize * sizeof(SHORT));
  190.  
  191.    /* shift gray down to 8 bits */
  192.   for(x=0; x<csize; x++) imap[x] = cmap[x].gray >> 8;
  193.  
  194.   for(x = 0; x < xsize; x++) err_buff[x] = (USHORT)imap[ *in++ ];
  195.   flag = 0;
  196.  
  197.   /* used to invert image */
  198.   if (x11_white & 0x01) invert = 0x00;
  199.   else invert = ~0x00;
  200.   threshold = 128;
  201.  
  202.   if (x11_bit_order == X11_MSB) { mask_start = 0x80; mask_end = 0x01; }
  203.   else { mask_start = 0x01; mask_end = 0x80; }
  204.  
  205.   for(y = 0; y < ysize; y++)
  206.   {
  207.     o_ptr = (UBYTE *)(out + (line_size * y));
  208.     /* double buffer error arrays */
  209.     n_ptr = c_ptr = err_buff;
  210.     if (flag == 0) { n_ptr += xsize; flag = 1; }
  211.     else { c_ptr += xsize; flag = 0;
  212.     }
  213.     data = 0x00;
  214.     mask = mask_start;
  215.     if (y < (ysize - 1) )  n_ptr[0] = (USHORT)imap[ *in++ ];
  216.  
  217.     for(x=0; x<xsize; x++)
  218.     {
  219.       if (*c_ptr >= threshold) { err = *c_ptr - 255; data |= mask; } 
  220.       else  err = *c_ptr;
  221.  
  222.       if (mask == mask_end) 
  223.     { *o_ptr++ = data^invert; data = 0x00; mask = mask_start; }
  224.       else if (mask_start == 0x80) mask >>= 1;
  225.            else mask <<= 1;
  226.       c_ptr++;
  227.  
  228.       if (xa_dither_flag == FALSE)
  229.       {
  230.         if (x < (xsize - 1) ) *n_ptr++ = imap[ *in++ ];
  231.       }
  232.       else
  233.       {
  234.         if (x < (xsize - 1) )  *c_ptr += (7 * err)/16;
  235.         if (y < (ysize - 1) )
  236.         {
  237.           if (x > 0) *n_ptr++ += (3 * err)/16;
  238.           *n_ptr++ += (5 * err)/16;
  239.           if (x < (xsize - 1) ) 
  240.           { *n_ptr = (USHORT)(imap[*in++]) + (SHORT)(err/16); n_ptr--; }
  241.         }
  242.       }
  243.     }
  244.     if (mask != mask_start) *o_ptr++ = data^invert; /* send out partial */
  245.  
  246.   }
  247.   FREE(err_buff,0x300); err_buff=0;
  248.   FREE(imap,0x301); imap=0;
  249. }
  250.  
  251. /* Routine to read a little endian long word.
  252.  */
  253. ULONG UTIL_Get_LSB_Long(fp)
  254. FILE *fp;
  255. {
  256.  ULONG ret;
  257.  
  258.  ret =  fgetc(fp);
  259.  ret |= fgetc(fp) << 8;
  260.  ret |= fgetc(fp) << 16;
  261.  ret |= fgetc(fp) << 24;
  262.  return ret;
  263. }
  264.  
  265. /* Routine to read a little endian half word.
  266.  */
  267. ULONG UTIL_Get_LSB_Short(fp)
  268. FILE *fp;
  269. {
  270.  ULONG ret;
  271.  
  272.  ret =  fgetc(fp);
  273.  ret |= fgetc(fp) << 8;
  274.  return ret;
  275. }
  276.  
  277. /* Routine to read a big endian long word.
  278.  */
  279. ULONG UTIL_Get_MSB_Long(fp)
  280. FILE *fp;
  281. {
  282.  ULONG ret;
  283.  
  284.  ret  = fgetc(fp) << 24;
  285.  ret |= fgetc(fp) << 16;
  286.  ret |= fgetc(fp) << 8;
  287.  ret |=  fgetc(fp);
  288.  return ret;
  289. }
  290.  
  291. /* Routine to read a big endian half word.
  292.  */
  293. LONG UTIL_Get_MSB_Short(fp)
  294. FILE *fp;
  295. {
  296.  LONG ret;
  297.  SHORT tmp;
  298.  
  299.  tmp  =  fgetc(fp) << 8;
  300.  tmp |=  fgetc(fp);
  301.  ret = tmp;
  302.  return ret;
  303. }
  304.  
  305. /* 
  306.  * Routine to read a big endian half word.
  307.  */
  308. ULONG UTIL_Get_MSB_UShort(fp)
  309. FILE *fp;
  310. {
  311.  ULONG ret;
  312.  
  313.  ret  =  fgetc(fp) << 8;
  314.  ret |=  fgetc(fp);
  315.  return ret;
  316. }
  317.  
  318. /*
  319.  *
  320.  */
  321. void UTIL_Mapped_To_Floyd(out,in,chdr_out,chdr_in,
  322.         xipos,yipos,xosize,yosize,xisize,yisize)
  323. UBYTE *out;        /* output (size of section) */
  324. UBYTE *in;        /* input image */
  325. XA_CHDR *chdr_out;    /* chdr to map to */
  326. XA_CHDR *chdr_in;    /* input images chdr */
  327. ULONG xipos,yipos;    /* section position within input buffer */
  328. ULONG xosize, yosize;    /* section size */
  329. ULONG xisize, yisize;    /* input buffer size */
  330. {
  331.   ULONG flag,csize_out,cflag;
  332.   ColorReg *cmap_in,*cmap_out;
  333.   register ULONG x,y;
  334.   ULONG shift_r,shift_g,shift_b,coff_out;
  335.   SHORT *err_buff0, *err_buff1, *e_ptr, *ne_ptr;
  336.   SHORT r_err,g_err,b_err;
  337.   UBYTE *o_ptr;
  338.  
  339.   cflag = (x11_display_type & XA_X11_COLOR)?TRUE:FALSE;
  340.  
  341.   if (!(x11_display_type & XA_X11_TRUE))
  342.   {
  343.     if (cmap_cache == 0) CMAP_Cache_Init();
  344.     if (chdr_out != cmap_cache_chdr)
  345.     {
  346.       DEBUG_LEVEL2 fprintf(stderr,"CACHE: clear new_chdr %lx\n",(ULONG)chdr_out);
  347.       CMAP_Cache_Clear();
  348.       cmap_cache_chdr = chdr_out;
  349.     }
  350.     shift_r = 3 * cmap_cache_bits;
  351.     shift_g = 2 * cmap_cache_bits;
  352.     shift_b = cmap_cache_bits;
  353.   }
  354.   
  355.   csize_out = chdr_out->csize;
  356.   cmap_out = chdr_out->cmap;
  357.   coff_out = chdr_out->coff;
  358.  
  359.   /* allocate error buffer and set up pointers */
  360.   e_ptr = err_buff1 = err_buff0 = (SHORT *)malloc(6 * xosize * sizeof(SHORT));
  361.   if (err_buff0 == 0) TheEnd1("UTIL_Mapped_To_Floyd: malloc err");
  362.   err_buff1 += (3 * xosize);
  363.   flag = 0;
  364.  
  365.   { /* POD NOTE: only do this with different cmaps */
  366.     register ULONG i,moff,msize,mcoff;
  367.     moff = chdr_in->moff;
  368.     mcoff = moff - chdr_in->coff;
  369.     msize = chdr_in->msize;
  370.     cmap_in = (ColorReg *)malloc((moff + msize) * sizeof(ColorReg));
  371.     for(i=0; i<msize; i++)
  372.     {
  373.       cmap_in[i + moff].red   = chdr_in->cmap[i + mcoff].red >> 8;
  374.       cmap_in[i + moff].green = chdr_in->cmap[i + mcoff].green >> 8;
  375.       cmap_in[i + moff].blue  = chdr_in->cmap[i + mcoff].blue >> 8;
  376.       cmap_in[i + moff].gray  = chdr_in->cmap[i + mcoff].gray >> 8;
  377.     }
  378.   }
  379.   {
  380.     register UBYTE *i_ptr = (UBYTE *)(in + (xisize * (yosize-1+yipos) + xipos));
  381.     x = xosize; while(x--)
  382.     {
  383.       register ULONG p = *i_ptr++;
  384.       *e_ptr++ = (USHORT)cmap_in[ p ].red   << 4;
  385.       *e_ptr++ = (USHORT)cmap_in[ p ].green << 4;
  386.       *e_ptr++ = (USHORT)cmap_in[ p ].blue  << 4;
  387.     }
  388.   }
  389.  
  390.   y = yosize; while(y--)
  391.   {
  392.     o_ptr = (UBYTE *)(out + (xosize * y * x11_bytes_pixel));
  393.     if (flag) { e_ptr = err_buff1; ne_ptr = err_buff0; flag = 0; }
  394.     else      { e_ptr = err_buff0; ne_ptr = err_buff1; flag = 1; }
  395.     if (y > 0)
  396.     {
  397.       register SHORT *tptr = ne_ptr;
  398.       register UBYTE *i_ptr = (UBYTE *)(in + (xisize * (y-1+yipos) + xipos));
  399.       x = xosize; while(x--)
  400.       {
  401.     register ULONG p = *i_ptr++;
  402.     *tptr++ = (USHORT)cmap_in[ p ].red   << 4;
  403.     *tptr++ = (USHORT)cmap_in[ p ].green << 4;
  404.     *tptr++ = (USHORT)cmap_in[ p ].blue  << 4;
  405.       }
  406.     }
  407.  
  408.     x = xosize; while(x--)
  409.     {
  410.       ULONG color_out,pix_out;
  411.       register SHORT r,g,b;
  412.  
  413.       r = (*e_ptr++)/16; if (r<0) r = 0; else if (r>255) r = 255;
  414.       g = (*e_ptr++)/16; if (g<0) g = 0; else if (g>255) g = 255;
  415.       b = (*e_ptr++)/16; if (b<0) b = 0; else if (b>255) b = 255;
  416.      
  417.       if (x11_display_type & XA_X11_TRUE)
  418.       {
  419.     ULONG tr,tg,tb;
  420.     pix_out = X11_Get_True_Color(r,g,b,8);
  421.     tr = ((pix_out & x11_red_mask)   >> x11_red_shift);
  422.     tg = ((pix_out & x11_green_mask) >> x11_green_shift);
  423.     tb = ((pix_out & x11_blue_mask)  >> x11_blue_shift);
  424.     r_err = r - (SHORT)(cmap_out[tr].red >> 8);
  425.     g_err = g - (SHORT)(cmap_out[tg].green >> 8);
  426.     b_err = b - (SHORT)(cmap_out[tb].blue >> 8);
  427.       }
  428.       else
  429.       {
  430.         register ULONG cache_i;
  431.         cache_i = (  ( (r << shift_r) & cmap_cache_rmask)
  432.                    | ( (g << shift_g) & cmap_cache_gmask)
  433.                    | ( (b << shift_b) & cmap_cache_bmask) ) >> 8;
  434.     if (cmap_cache[cache_i] == 0xffff)
  435.     {
  436.       color_out = CMAP_Find_Closest(cmap_out,csize_out,r,g,b,8,8,8,cflag);
  437.       cmap_cache[cache_i] = (SHORT)color_out;
  438.     }
  439.     else color_out = (ULONG)cmap_cache[cache_i];
  440.     pix_out = color_out + coff_out;
  441.         r_err = r - (SHORT)(cmap_out[color_out].red >> 8);
  442.         g_err = g - (SHORT)(cmap_out[color_out].green >> 8);
  443.         b_err = b - (SHORT)(cmap_out[color_out].blue >> 8);
  444.       }
  445.  
  446.       if (x11_bytes_pixel == 1) *o_ptr++ = (UBYTE)pix_out;
  447.       else if (x11_bytes_pixel == 2)
  448.       { USHORT *so_ptr = (USHORT *)(o_ptr);
  449.         *so_ptr = (USHORT)pix_out; o_ptr +=2; }
  450.       else { ULONG *lo_ptr = (ULONG *)(o_ptr);
  451.              *lo_ptr = (ULONG)pix_out; o_ptr +=4; }
  452.  
  453.       if (x)
  454.       {
  455.     *e_ptr   += 7 * r_err;
  456.     e_ptr[1] += 7 * g_err;
  457.     e_ptr[2] += 7 * b_err;
  458.       }
  459.       if (y)
  460.       {
  461.         if (x < (xosize-1) ) /* not 1st of line */
  462.     {
  463.       *ne_ptr++ += 3 * r_err;
  464.       *ne_ptr++ += 3 * g_err;
  465.       *ne_ptr++ += 3 * b_err;
  466.     }
  467.         *ne_ptr   += 5 * r_err;
  468.         ne_ptr[1] += 5 * g_err;
  469.         ne_ptr[2] += 5 * b_err;
  470.         if (x)
  471.         {
  472.       ne_ptr[3] += r_err;
  473.       ne_ptr[4] += g_err;
  474.       ne_ptr[5] += b_err;
  475.     }
  476.       }
  477.     } /* end of x */
  478.   } /* end of y */
  479.   if (err_buff0) FREE(err_buff0,0x302);
  480.   if (cmap_in) FREE(cmap_in,0x305);
  481.   err_buff0 = 0; cmap_in = 0;
  482. }
  483.  
  484. /*
  485.  * Function to Scale <x,y> positions and sizes
  486.  *
  487.  */
  488.  
  489. void
  490. UTIL_Scale_Pos_Size(xpos,ypos,xsize,ysize,xi_scale,yi_scale,
  491.                     xo_scale,yo_scale)
  492. LONG *xpos,*ypos;     /* input/output positions */
  493. LONG *xsize,*ysize;     /* input/output sizes */
  494. LONG xi_scale,yi_scale; /* input scale/image size */
  495. LONG xo_scale,yo_scale; /* output scale/image size */
  496. {
  497.   LONG ixp,iyp,oxp,oyp;
  498.   LONG ixsize,iysize,oxsize,oysize;
  499.  
  500.   ixp = *xpos;      iyp = *ypos;
  501.   ixsize = *xsize;  iysize = *ysize;
  502.  
  503.   oxp = (ixp * xo_scale) / xi_scale;
  504.   if ( ((oxp * xi_scale) / xo_scale) < ixp ) oxp++;
  505.   oxsize = (((ixp + ixsize) * xo_scale) / xi_scale) + 1 - oxp;
  506.   if ( (((oxp+oxsize-1) * xi_scale) / xo_scale) >= (ixp+ixsize) ) oxsize--;
  507.  
  508.   oyp = (iyp * yo_scale) / yi_scale;
  509.   if ( ((oyp * yi_scale) / yo_scale) < iyp ) oyp++;
  510.   oysize = (((iyp + iysize) * yo_scale) / yi_scale) + 1 - oyp;
  511.   if ( (((oyp+oysize-1) * yi_scale) / yo_scale) >= (iyp+iysize) ) oysize--;
  512.  
  513.   *xpos = oxp;        *ypos = oyp;
  514.   *xsize = oxsize;    *ysize = oysize;
  515. }
  516.  
  517.  
  518. /*
  519.  * Function to Scale <x,y> positions
  520.  *
  521.  *  new <x,y> positions returned in xopos,yopos;
  522.  */
  523.  
  524. void
  525. UTIL_Scale_Buffer_Pos(xpos,ypos,xi_scale,yi_scale,
  526.                     xo_scale,yo_scale)
  527. LONG *xpos,*ypos;     /* input/output positions */
  528. LONG xi_scale,yi_scale; /* input scale/image size */
  529. LONG xo_scale,yo_scale; /* output scale/image size */
  530. {
  531.   LONG ixp,iyp,oxp,oyp;
  532.  
  533.   ixp = *xpos; iyp = *ypos;
  534.  
  535.   oxp = (ixp * xo_scale) / xi_scale;
  536.   if ( ((oxp * xi_scale) / xo_scale) < ixp ) oxp++;
  537.  
  538.   oyp = (iyp * yo_scale) / yi_scale;
  539.   if ( ((oyp * yi_scale) / yo_scale) < iyp ) oyp++;
  540.  
  541.   *xpos = oxp;        *ypos = oyp;
  542. }
  543.  
  544.  
  545. /*
  546.  * Function to get Scaling Buffer Coordinates.
  547.  *     returns TRUE if need to scale while buffering
  548.  *    returns FALSE if you don't 
  549.  *
  550.  * NOTE: This should only be called within XXX_Read_File or else
  551.  *       scale isn't guaranteed to be valid.
  552.  * ACT_Setup_Mapped is okay since it has the same limitations.
  553.  */
  554. ULONG UTIL_Get_Buffer_Scale(width,height,buffx_o,buffy_o)
  555. ULONG width,height;     /* width, height of anim */
  556. ULONG *buffx_o,*buffy_o; /* scaled width, height of anim */
  557. {
  558.  ULONG need_to_scale;
  559.  ULONG buff_x,buff_y;
  560.  
  561.   /* Figure out buffer scaling */
  562.   if ( (xa_buff_x != 0) && (xa_buff_y != 0) )
  563.         { buff_x = xa_buff_x; buff_y = xa_buff_y; }
  564.   else if (xa_buff_x != 0) /* if just x, then adjust y */
  565.         { buff_x = xa_buff_x; buff_y = (height * xa_buff_x) / width; }
  566.   else if (xa_buff_y != 0) /* if just y, then adjust x */
  567.         { buff_y = xa_buff_y; buff_x = (width * xa_buff_y) / height; }
  568.   else
  569.   {
  570.      /* handle any scaling */
  571.     buff_x = (ULONG)((float)(width) * xa_bscalex);
  572.     if (buff_x == 0) buff_x = width;
  573.     buff_y = (ULONG)((float)(height) * xa_bscaley);
  574.     if (buff_y == 0) buff_y = height;
  575.   }
  576.   if ((buff_x != width) || (buff_y != height)) need_to_scale = TRUE;
  577.   else need_to_scale = FALSE;
  578.   *buffx_o = buff_x; *buffy_o = buff_y;
  579.   return(need_to_scale);
  580. }
  581.  
  582. /*
  583.  * Function to allocate buffer for Scaling
  584.  *
  585.  */
  586. UBYTE *UTIL_Alloc_Scaled(xi_size,yi_size,xi_scale,yi_scale,
  587.     xo_scale,yo_scale,pix_size,xo_pos,yo_pos,bitmap_flag)
  588. ULONG xi_size,yi_size;   /* size of section */
  589. ULONG xi_scale,yi_scale; /* size of full input image */
  590. ULONG xo_scale,yo_scale; /* size of full output image */
  591. ULONG pix_size;          /* pixel size */
  592. ULONG xo_pos,yo_pos;     /* pos of section in input buffer */
  593. ULONG bitmap_flag;     /* if true, then alloc for a bitmap */
  594.  
  595. {
  596.   ULONG sx,sy,xsize,ysize;
  597.   UBYTE *out;
  598.  
  599.   sx = (xo_pos * xo_scale) / xi_scale;
  600.   if ( ((sx * xi_scale) / xo_scale) < xo_pos ) sx++;
  601.   xsize = (((xo_pos + xi_size) * xo_scale) / xi_scale) + 1 - sx;
  602.   if ( (((sx+xsize-1) * xi_scale) / xo_scale) >= (xo_pos+xi_size) ) xsize--;
  603.  
  604.   sy = (yo_pos * yo_scale) / yi_scale;
  605.   if ( ((sy * yi_scale) / yo_scale) < yo_pos ) sy++;
  606.   ysize = (((yo_pos + yi_size) * yo_scale) / yi_scale) + 1 - sy;
  607.   if ( (((sy+ysize-1) * yi_scale) / yo_scale) >= (yo_pos+yi_size) ) ysize--;
  608.  
  609.   if ( (xsize==0) || (ysize==0) )
  610.   {
  611.     DEBUG_LEVEL1 fprintf(stderr,"SCALE: zero size %ld %ld\n",xsize,ysize);
  612.     return(0);
  613.   }
  614.  
  615. DEBUG_LEVEL1 fprintf(stderr,"AllocScaled: xy %ld %ld  t %ld\n",
  616.   xsize,ysize,(xsize * ysize * pix_size));
  617.  
  618.   if (bitmap_flag==TRUE)
  619.   {
  620.     ULONG line_size;
  621.     line_size = X11_Get_Bitmap_Width(xsize) / 8;
  622.     out = (UBYTE *)malloc(line_size * ysize);
  623.   }
  624.   else out = (UBYTE *)malloc(xsize * ysize * pix_size);
  625.   if (out==0) TheEnd1("UTIL_Alloc_Scaled: malloc err");
  626.   return(out);
  627. }
  628.  
  629. /*
  630.  * Function to Scale a Mapped Image 
  631.  *
  632.  */
  633. UBYTE *UTIL_Scale_Mapped(out,in,xi_pos,yi_pos,xi_size,yi_size,
  634.     xi_buff_size,xi_scale,yi_scale,xo_scale,yo_scale,pix_size,
  635.     xo_pos,yo_pos,xo_size,yo_size,chdr)
  636. UBYTE *out;         /* output buffer, if 0 then one is created */
  637. UBYTE *in;         /* input image buffer */
  638. ULONG xi_pos,yi_pos;     /* pos of section in input buffer */
  639. ULONG xi_size,yi_size;   /* size of section */
  640. ULONG xi_buff_size;      /* row size of input buffer in bytes */
  641. ULONG xi_scale,yi_scale; /* size of full input image */
  642. ULONG xo_scale,yo_scale; /* size of full output image */
  643. ULONG pix_size;         /* pixel size */
  644. ULONG *xo_pos,*yo_pos;   /* I screen pos/O pos of section in output buffer */
  645. ULONG *xo_size,*yo_size; /* O size of outgoing section */
  646. XA_CHDR *chdr;
  647. /* note: pos of section in output buffer is always 0,0 */
  648. {
  649.   ULONG i,y,sx,sy,xvp,yvp,xsize,ysize,xoff;
  650.  
  651.  
  652.   xvp = *xo_pos; yvp = *yo_pos;
  653.   sx = (xvp * xo_scale) / xi_scale;
  654.   if ( ((sx * xi_scale) / xo_scale) < xvp ) sx++;
  655.   xsize = (((xvp + xi_size) * xo_scale) / xi_scale) + 1 - sx;
  656.   if ( (((sx+xsize-1) * xi_scale) / xo_scale) >= (xvp+xi_size) ) xsize--;
  657.  
  658.   sy = (yvp * yo_scale) / yi_scale;
  659.   if ( ((sy * yi_scale) / yo_scale) < yvp ) sy++;
  660.   ysize = (((yvp + yi_size) * yo_scale) / yi_scale) + 1 - sy;
  661.   if ( (((sy+ysize-1) * yi_scale) / yo_scale) >= (yvp+yi_size) ) ysize--;
  662.  
  663.   xoff = xvp - xi_pos;
  664.   if ( (xsize==0) || (ysize==0) ) 
  665.   {
  666.     DEBUG_LEVEL1 fprintf(stderr,"SCALE: zero size %ld %ld\n",xsize,ysize);
  667.     *xo_pos = *yo_pos = *xo_size = *yo_size = 0;
  668.     return(0);
  669.   }
  670.  
  671.   /* use scale buffer if necessary */
  672.   if (out == 0)
  673.   {
  674.     ULONG tsize = xsize * ysize * pix_size;
  675.     XA_REALLOC(xa_scale_buff,xa_scale_buff_size,tsize);
  676.     out = (UBYTE *)xa_scale_buff;
  677.   }
  678.  
  679.   /* readjust row cache buffer if necessary */
  680.   if (xsize > xa_scale_row_size)
  681.   {
  682.     ULONG *tmp;
  683.     if (xa_scale_row_buff == 0) tmp = (ULONG *) malloc(xsize * sizeof(ULONG) );
  684.     else tmp = (ULONG *) realloc(xa_scale_row_buff, xsize * sizeof(ULONG) );
  685.     if (tmp == 0) TheEnd1("UTIL_Scale_Mapped: row malloc err\n");
  686.     xa_scale_row_buff = tmp;    xa_scale_row_size = xsize;
  687.   }
  688.  
  689.   y = sx; for(i = 0; i < xsize; i++,y++)
  690.     xa_scale_row_buff[i] = ((y * xi_scale) / xo_scale ) - xoff;
  691.  
  692.   if (chdr==0) /* no mapping */
  693.   {
  694.     register ULONG x,yoff;
  695.     yoff = yvp - yi_pos;
  696.     if (pix_size == 4)
  697.     {
  698.       register ULONG *optr = (ULONG *)out;
  699.       for(y=sy; y< (sy + ysize); y++)
  700.       { register ULONG *in_r_ptr = 
  701.         (ULONG *)(in+(((y*yi_scale)/yo_scale)-yoff)*xi_buff_size);
  702.         for(x = 0; x < xsize; x++) *optr++ = in_r_ptr[ xa_scale_row_buff[x] ];
  703.       }
  704.     }
  705.     else if (pix_size == 2)
  706.     {
  707.       register USHORT *optr = (USHORT *)out;
  708.       for(y=sy; y< (sy + ysize); y++)
  709.       { register USHORT *in_r_ptr = 
  710.         (USHORT *)(in+(((y*yi_scale)/yo_scale)-yoff)*xi_buff_size);
  711.         for(x = 0; x < xsize; x++) *optr++ = in_r_ptr[ xa_scale_row_buff[x] ];
  712.       }
  713.     }
  714.     else
  715.     {
  716.       register UBYTE *optr = (UBYTE *)out;
  717.       for(y=sy; y< (sy + ysize); y++)
  718.       { register UBYTE *in_r_ptr = 
  719.         (UBYTE *)(in+(((y*yi_scale)/yo_scale)-yoff)*xi_buff_size);
  720.         for(x = 0; x < xsize; x++) *optr++ = in_r_ptr[ xa_scale_row_buff[x] ];
  721.       }
  722.     }
  723.   }
  724.   else /* remap as we scale */
  725.   {
  726.     register ULONG x,yoff,moff,*map;
  727.     map  = chdr->map; moff = chdr->moff; yoff = yvp - yi_pos;
  728.     if (pix_size == 4)
  729.     {
  730.       register ULONG *optr = (ULONG *)out;
  731.       for(y=sy; y< (sy + ysize); y++)
  732.       { register UBYTE *in_r_ptr = 
  733.         (UBYTE *)(in+(((y*yi_scale)/yo_scale)-yoff)*xi_buff_size);
  734.     if (moff) for(x = 0; x < xsize; x++) 
  735.         *optr++ = (ULONG)map[in_r_ptr[ xa_scale_row_buff[x]]-moff];
  736.     else for(x = 0; x < xsize; x++) 
  737.         *optr++ = (ULONG)map[in_r_ptr[ xa_scale_row_buff[x]]];
  738.       }
  739.     }
  740.     else if (pix_size == 2)
  741.     {
  742.       register USHORT *optr = (USHORT *)out;
  743.       for(y=sy; y< (sy + ysize); y++)
  744.       { register UBYTE *in_r_ptr = 
  745.         (UBYTE *)(in+(((y*yi_scale)/yo_scale)-yoff)*xi_buff_size);
  746.     if (moff) for(x = 0; x < xsize; x++) 
  747.         *optr++ = (USHORT)map[in_r_ptr[ xa_scale_row_buff[x]]-moff];
  748.     else for(x = 0; x < xsize; x++) 
  749.         *optr++ = (USHORT)map[in_r_ptr[ xa_scale_row_buff[x]]];
  750.       }
  751.     }
  752.     else
  753.     {
  754.       register UBYTE *optr = (UBYTE *)out;
  755.       for(y=sy; y< (sy + ysize); y++)
  756.       { register UBYTE *in_r_ptr = 
  757.         (UBYTE *)(in+(((y*yi_scale)/yo_scale)-yoff)*xi_buff_size);
  758.     if (moff) for(x = 0; x < xsize; x++) 
  759.         *optr++ = (UBYTE)map[in_r_ptr[ xa_scale_row_buff[x]]-moff];
  760.     else for(x = 0; x < xsize; x++) 
  761.         *optr++ = (UBYTE)map[in_r_ptr[ xa_scale_row_buff[x]]];
  762.       }
  763.     }
  764.   }
  765.   *yo_pos = sy; *yo_size = ysize;
  766.   *xo_pos = sx; *xo_size = xsize;
  767.   return(out);
  768. }
  769.  
  770.  
  771. /*
  772.  * for now assum xi_pos=yi_pos=0 and size are multiple of 8s 
  773.  *
  774.  */
  775. UBYTE *UTIL_Scale_Bitmap(out,in,xi_size,yi_size,
  776.     xi_line_size,xi_scale,yi_scale,xo_scale,yo_scale,
  777.     xo_pos,yo_pos,xo_size,yo_size,ibit_order,obit_order)
  778. UBYTE *out,*in;
  779. ULONG xi_size,yi_size;   /* size of section */
  780. ULONG xi_line_size;      /* row size of input buffer in bytes*/
  781. ULONG xi_scale,yi_scale; /* size of full input image */
  782. ULONG xo_scale,yo_scale; /* size of full output image */
  783. ULONG *xo_pos,*yo_pos;   /* pos of section in input/output buffer */
  784. ULONG *xo_size,*yo_size; /* size of outgoing section */
  785. ULONG ibit_order;     /* input bit_order */
  786. ULONG obit_order;     /* output bit_order */
  787. {
  788.   ULONG xo_line_size;
  789.   ULONG i,y,sx,sy,xvp,yvp,xsize,ysize;
  790.   ULONG *row_b_ptr;
  791.   UBYTE *row_msk_ptr,mask_start,mask_end;
  792.  
  793.   xvp = *xo_pos; yvp = *yo_pos;
  794.   sx = (xvp * xo_scale) / xi_scale;
  795.   if ( ((sx * xi_scale) / xo_scale) < xvp ) sx++;
  796.   xsize = (((xvp + xi_size) * xo_scale) / xi_scale) + 1 - sx;
  797.   if ( (((sx+xsize-1) * xi_scale) / xo_scale) >= (xvp+xi_size) ) xsize--;
  798.  
  799.   sy = (yvp * yo_scale) / yi_scale;
  800.   if ( ((sy * yi_scale) / yo_scale) < yvp ) sy++;
  801.   ysize = (((yvp + yi_size) * yo_scale) / yi_scale) + 1 - sy;
  802.   if ( (((sy+ysize-1) * yi_scale) / yo_scale) >= (yvp+yi_size) ) ysize--;
  803.  
  804. DEBUG_LEVEL1 fprintf(stderr,"SCALE BITMAP: siz %ldx%ld -> %ldx%ld\n",
  805.     xi_size,yi_size,xsize,ysize);
  806. DEBUG_LEVEL1 fprintf(stderr,"SCALE BITMAP: pos %ldx%ld -> %ldx%ld\n",
  807.     xvp,yvp,sx,sy);
  808.  
  809.   if ( (xsize==0) || (ysize==0) ) 
  810.   {
  811.     DEBUG_LEVEL1 fprintf(stderr,"SCALE: zero size %ld %ld\n",xsize,ysize);
  812.     *xo_size = *yo_size = 0;
  813.     return(0);
  814.   }
  815.   xo_line_size = X11_Get_Bitmap_Width(xsize) / 8;
  816.   /* use scale buffer if necessary */
  817.   if (out == 0)
  818.   {
  819.     ULONG tsize = ysize * xo_line_size;
  820.     XA_REALLOC(xa_scale_buff,xa_scale_buff_size,tsize);
  821.     out = (UBYTE *)xa_scale_buff;
  822.   }
  823.  
  824.   /* readjust row cache buffer if necessary */
  825.   if ( (xsize<<1) > xa_scale_row_size)
  826.   {
  827.     ULONG *tmp;
  828.     if (xa_scale_row_buff == 0) tmp = (ULONG *) malloc(xsize * sizeof(ULONG) );
  829.     else tmp = (ULONG *) realloc(xa_scale_row_buff,(xsize<<1)*sizeof(ULONG));
  830.     if (tmp == 0) TheEnd1("UTIL_Scale_Mapped: row malloc err\n");
  831.     xa_scale_row_buff = tmp;    xa_scale_row_size = (xsize<<1);
  832.   }
  833.   row_b_ptr = xa_scale_row_buff;
  834.   row_msk_ptr = (UBYTE *)&xa_scale_row_buff[xsize];
  835.  
  836.   y = sx;
  837.   for(i = 0; i < xsize; i++,y++)
  838.   {
  839.     register ULONG x = ((y * xi_scale) / xo_scale) - xvp;
  840.     row_b_ptr[i] = x/8;
  841.     if (ibit_order == X11_LSB) row_msk_ptr[i] = 0x01 << (x%8);
  842.     else row_msk_ptr[i] = 0x01 << (7 - (x%8));
  843.   }
  844.   if (obit_order == X11_MSB) { mask_start = 0x80; mask_end = 0x01; }
  845.   else { mask_start = 0x01; mask_end = 0x80; }
  846.   for(y=sy; y < (sy+ysize);y++)
  847.   {
  848.     register ULONG x;
  849.     register UBYTE omsk,odat;
  850.     register UBYTE *iptr,*optr;
  851.     iptr = (UBYTE *)(in + (((y * yi_scale) / yo_scale)-yvp) * xi_line_size);
  852.     optr = (UBYTE *)(out + ((y - sy) * xo_line_size));
  853.     omsk = mask_start; odat = 0;
  854.     for(x=0; x<xsize; x++)
  855.     {
  856.       if ( iptr[ row_b_ptr[x] ] & row_msk_ptr[x] ) odat |= omsk;
  857.       if (omsk == mask_end) { *optr++ = odat; omsk = mask_start; odat = 0; }
  858.       else if (mask_start == 0x01) omsk <<= 1; else omsk >>= 1;
  859.     }
  860.     if (omsk) *optr++ = odat;
  861.   }
  862.   *xo_pos = sx;     *yo_pos = sy;
  863.   *xo_size = xsize; *yo_size = ysize;
  864.   return(out);
  865. }
  866.  
  867. /**********************
  868.  * UTIL_RGB_To_Map
  869.  *
  870.  **********************/
  871. UBYTE *UTIL_RGB_To_Map(out,in,chdr,xsize,ysize,free_in_flag)
  872. UBYTE *out,*in;
  873. XA_CHDR *chdr;
  874. ULONG xsize,ysize;
  875. ULONG free_in_flag;
  876. {
  877.   ULONG i,shift_r,shift_g,shift_b,pic_size;
  878.   UBYTE *t_pic,*iptr,*optr;
  879.   ULONG csize,coff;
  880.  
  881.   DEBUG_LEVEL1 fprintf(stderr,"UTIL_RGB_To_Map\n");
  882.   pic_size = xsize * ysize;
  883.   if (out == 0)
  884.   {
  885.     t_pic = (UBYTE *)malloc( XA_PIC_SIZE(pic_size) );
  886.     if (t_pic == 0) TheEnd1("RGB: t_pic malloc err");
  887.   } else t_pic = out;
  888.  
  889.   if (cmap_cache == 0) CMAP_Cache_Init();
  890.   if (chdr != cmap_cache_chdr)
  891.   {
  892.     DEBUG_LEVEL2 fprintf(stderr,"CACHE: clear new_chdr %lx\n",
  893.                                                         (ULONG)chdr);
  894.     CMAP_Cache_Clear();
  895.     cmap_cache_chdr = chdr;
  896.   }
  897.   shift_r = 3 * cmap_cache_bits;
  898.   shift_g = 2 * cmap_cache_bits;
  899.   shift_b = cmap_cache_bits;
  900.  
  901.  
  902.   csize = chdr->csize;
  903.   coff = chdr->coff;
  904.   iptr = in;
  905.   optr = t_pic;
  906.   for(i=0; i < pic_size; i++)
  907.   {
  908.     register ULONG color_out,r,g,b;
  909.     register ULONG cache_i;
  910.  
  911.     r = (ULONG)(*iptr++); g = (ULONG)(*iptr++); b = (ULONG)(*iptr++);
  912.     cache_i  = (ULONG)(  (  ( (r << shift_r) & cmap_cache_rmask)
  913.                           | ( (g << shift_g) & cmap_cache_gmask)
  914.                           | ( (b << shift_b) & cmap_cache_bmask)
  915.                          ) >> 8);
  916.     if (cmap_cache[cache_i] == 0xffff)
  917.     {
  918.       color_out = coff +
  919.                 CMAP_Find_Closest(chdr->cmap,csize,r,g,b,8,8,8,TRUE);
  920.       cmap_cache[cache_i] = (USHORT)color_out;
  921.     }
  922.     else color_out = (ULONG)cmap_cache[cache_i];
  923.  
  924.     *optr++ = (UBYTE)(color_out);
  925.  
  926.   }
  927.   if (free_in_flag == TRUE) FREE(in,0x999); in=0;
  928.   return(t_pic);
  929. }
  930.  
  931. /**********************
  932.  *
  933.  **********************/
  934. UBYTE *UTIL_RGB_To_FS_Map(out,in,chdr,xsize,ysize,free_in_flag)
  935. UBYTE *out,*in;
  936. XA_CHDR *chdr;
  937. ULONG xsize,ysize;
  938. ULONG free_in_flag;
  939. {
  940.   ULONG flag,csize,xsize3;
  941.   ColorReg *cmap;
  942.   register ULONG x,y;
  943.   ULONG shift_r,shift_g,shift_b,coff;
  944.   SHORT *err_buff0, *err_buff1, *e_ptr, *ne_ptr;
  945.   SHORT r_err,g_err,b_err;
  946.   UBYTE *o_ptr,*tpic;
  947.  
  948.   DEBUG_LEVEL1 fprintf(stderr,"UTIL_RGB_To_FS_Map\n");
  949.  
  950.   if (out == 0)
  951.   {
  952.     tpic = (UBYTE *)malloc( XA_PIC_SIZE(xsize * ysize) );
  953.     if (tpic == 0) TheEnd1("UTIL_RGB_To_FS_Map: malloc err");
  954.   } else tpic = out;
  955.  
  956.   if (cmap_cache == 0) CMAP_Cache_Init();
  957.  
  958.   if (chdr != cmap_cache_chdr)
  959.   {
  960.     DEBUG_LEVEL2 fprintf(stderr,"CACHE: clear new_chdr %lx\n",(ULONG)chdr);
  961.     CMAP_Cache_Clear();
  962.     cmap_cache_chdr = chdr;
  963.   }
  964.   shift_r = 3 * cmap_cache_bits;
  965.   shift_g = 2 * cmap_cache_bits;
  966.   shift_b = cmap_cache_bits;
  967.   
  968.   csize = chdr->csize;
  969.   cmap = chdr->cmap;
  970.   coff = chdr->coff;
  971.  
  972.   /* allocate error buffer and set up pointers */
  973.   xsize3 = xsize * 3;
  974.   e_ptr = err_buff0 = (SHORT *)malloc(6 * xsize * sizeof(SHORT) );
  975.   if (err_buff0 == 0) TheEnd1("UTIL_Mapped_To_Floyd: malloc err");
  976.   err_buff1 = (SHORT *)(err_buff0 + (xsize3 * sizeof(SHORT) ) ); 
  977.   flag = 0;
  978.  
  979.   {
  980.     register UBYTE *i_ptr = (UBYTE *)( in + (xsize3 * (ysize-1)));
  981.     x = xsize; while(x--)
  982.     {
  983.       *e_ptr++ = (USHORT)(*i_ptr++) << 4;
  984.       *e_ptr++ = (USHORT)(*i_ptr++) << 4;
  985.       *e_ptr++ = (USHORT)(*i_ptr++) << 4;
  986.     }
  987.   }
  988.  
  989.   y = ysize; while(y--)
  990.   {
  991.     o_ptr = (UBYTE *)(tpic + (xsize * y));
  992.     if (flag) { e_ptr = err_buff1; ne_ptr = err_buff0; flag = 0; }
  993.     else      { e_ptr = err_buff0; ne_ptr = err_buff1; flag = 1; }
  994.     if (y > 0)
  995.     {
  996.       register SHORT *tptr = ne_ptr;
  997.       register UBYTE *i_ptr = (UBYTE *)(in + (xsize3 * (y-1)));
  998.       x = xsize; while(x--)
  999.       {
  1000.     *tptr++ = (USHORT)(*i_ptr++) << 4;
  1001.     *tptr++ = (USHORT)(*i_ptr++) << 4;
  1002.     *tptr++ = (USHORT)(*i_ptr++) << 4;
  1003.       }
  1004.     }
  1005.  
  1006.     x = xsize; while(x--)
  1007.     {
  1008.       ULONG color_out;
  1009.       register SHORT r,g,b;
  1010.       register ULONG cache_i;
  1011.  
  1012.       r = (*e_ptr++)/16; if (r<0) r = 0; else if (r>255) r = 255;
  1013.       g = (*e_ptr++)/16; if (g<0) g = 0; else if (g>255) g = 255;
  1014.       b = (*e_ptr++)/16; if (b<0) b = 0; else if (b>255) b = 255;
  1015.      
  1016.       cache_i = (  ( (r << shift_r) & cmap_cache_rmask)
  1017.                  | ( (g << shift_g) & cmap_cache_gmask)
  1018.                  | ( (b << shift_b) & cmap_cache_bmask) ) >> 8;
  1019.  
  1020.       if (cmap_cache[cache_i] == 0xffff)
  1021.       {
  1022.         color_out = CMAP_Find_Closest(cmap,csize,r,g,b,8,8,8,TRUE);
  1023.         cmap_cache[cache_i] = (SHORT)color_out;
  1024.       }
  1025.       else color_out = (ULONG)cmap_cache[cache_i];
  1026.       
  1027.       *o_ptr++ = (UBYTE)(color_out + coff);
  1028.  
  1029.       r_err = r - (SHORT)(cmap[color_out].red >> 8);
  1030.       g_err = g - (SHORT)(cmap[color_out].green >> 8);
  1031.       b_err = b - (SHORT)(cmap[color_out].blue >> 8);
  1032.  
  1033.       if (x)
  1034.       {
  1035.     *e_ptr   += 7 * r_err;
  1036.     e_ptr[1] += 7 * g_err;
  1037.     e_ptr[2] += 7 * b_err;
  1038.       }
  1039.       if (y)
  1040.       {
  1041.         if (x < (xsize-1) ) /* not 1st of line */
  1042.     {
  1043.       *ne_ptr++ += 3 * r_err;
  1044.       *ne_ptr++ += 3 * g_err;
  1045.       *ne_ptr++ += 3 * b_err;
  1046.     }
  1047.         *ne_ptr   += 5 * r_err;
  1048.         ne_ptr[1] += 5 * g_err;
  1049.         ne_ptr[2] += 5 * b_err;
  1050.         if (x)
  1051.         {
  1052.       ne_ptr[3] += r_err;
  1053.       ne_ptr[4] += g_err;
  1054.       ne_ptr[5] += b_err;
  1055.     }
  1056.       }
  1057.     } /* end of x */
  1058.   } /* end of y */
  1059.   if (err_buff0) { FREE(err_buff0,0x302); err_buff0=0; }
  1060.   if (free_in_flag == TRUE) FREE(in,0x999);
  1061.   return(tpic);
  1062. }
  1063.  
  1064. void
  1065. UTIL_Pack_Image(out,in,xsize,ysize)
  1066. UBYTE *out;
  1067. UBYTE *in;
  1068. ULONG xsize,ysize;
  1069. {
  1070.   UBYTE *o_ptr;
  1071.   ULONG x,y,shft_msk;
  1072.   LONG shft_start,shft_end,shft_inc;
  1073.  
  1074.   if (x11_bits_per_pixel == 4)
  1075.   { shft_msk = 0x0f;
  1076.     if (x11_byte_order == X11_MSB) {shft_start=4; shft_end=0; shft_inc= -4;}
  1077.     else               {shft_start=0; shft_end=4; shft_inc=  4;}
  1078.   }
  1079.   else if (x11_bits_per_pixel == 2)
  1080.   { shft_msk = 0x03;
  1081.     if (x11_byte_order == X11_MSB) {shft_start=6; shft_end=0; shft_inc= -2;}
  1082.     else               {shft_start=0; shft_end=6; shft_inc=  2;}
  1083.   }
  1084.   else /* unsupported depth */
  1085.   {
  1086.     fprintf(stderr,"X11 Packing of bits %ld to depth %ld not yet supported\n",
  1087.     x11_bits_per_pixel,x11_depth);
  1088.     return;
  1089.   }
  1090.  
  1091.   o_ptr = out;
  1092.   for(y=0;y<ysize;y++)
  1093.   {
  1094.     register ULONG data;
  1095.     register LONG shft;
  1096.     shft = shft_start;
  1097.     for(x=0;x<xsize;x++)
  1098.     {
  1099.     if (shft != shft_end) /* still creating byte */
  1100.     {
  1101.       data = ((*in++) & shft_msk) << shft; 
  1102.       shft += shft_inc;
  1103.     }
  1104.     else /* at the end */
  1105.     {
  1106.       *o_ptr++ = data | (((*in++) & shft_msk) << shft);
  1107.       shft = shft_start;
  1108.     } 
  1109.     }
  1110.     if (shft != shft_start) *o_ptr++ = data; /* partial byte */
  1111.   } /* end of y loop */
  1112. }
  1113.